<!-- +----------------------------------------------------------------------
| 麦沃德科技赋能开发者，助力中小企业发展 
+----------------------------------------------------------------------
| Copyright (c) 2017～2024  www.wdadmin.cn    All rights reserved.
+----------------------------------------------------------------------
| 沃德代驾系统并不是自由软件，不加密，并不代表开源，未经许可不可自由转售和商用
+----------------------------------------------------------------------
| Author: MY WORLD Team <bd@maiwd.cn>   www.wdadmin.cn
+----------------------------------------------------------------------
| 订单详情 开发者: 麦沃德科技-半夏
+---------------------------------------------------------------------- -->

<template>
	<page-meta :page-style="'overflow:' + (pageShow ? 'hidden' : 'visible')"></page-meta>
	<view class="container flex-column" :style="{'--theme-color': themeColor}" v-if="loadEnd">
		<view class="container-map flex-item">
			<map id="map" class="map-box" :latitude="mapInfo.latitude" :longitude="mapInfo.longitude" :markers="showMarkers" :polyline="polyline" @regionchange="regionchange">
				<cover-view slot="callout" class="map-callout">
					<template v-if="orderState == 'pending'">
						<cover-view class="callout-address" :marker-id="1">
							<cover-view class="address-name">{{orderInfo.from_address}}</cover-view>
						</cover-view>
						<cover-view class="callout-address" :marker-id="2">
							<cover-view class="address-name">{{orderInfo.to_address}}</cover-view>
						</cover-view>
					</template>
					<template v-else-if="orderState == 'accepted' && orderInfo.driver_arrive_status == 'arrived'">
						<cover-view class="callout-box" :marker-id="5">
							<cover-view class="box-title">已到达指定地点</cover-view>
							<cover-view class="box-subtitle">请尽快联系乘客</cover-view>
						</cover-view>
					</template>
				</cover-view>
			</map>
		</view>
		<view class="container-main" :style="{background: orderInfo.state == 'pending' ? '#F7F7F7' : '#FFF'}">
			<!-- 待接单 -->
			<view class="main-content" v-if="orderInfo.state == 'pending'">
				<view class="content-card">
					<view class="card-title">{{orderInfo.departure_time}}</view>
					<view class="card-group flex align-items-center" :style="{'--group-color': '#242629'}">
						<view class="group-point"></view>
						<view class="group-text">{{orderInfo.from_address}}</view>
					</view>
					<view class="card-group flex align-items-center" :style="{'--group-color': themeColor}">
						<view class="group-point"></view>
						<view class="group-text">{{orderInfo.to_address}}</view>
					</view>
				</view>
				<view class="content-column" style="background: #FFF;">
					<view class="column-title">全程距离</view>
					<view class="column-value">{{orderInfo.distance}}</view>
				</view>
				<view class="content-column" style="background: #FFF;" v-if="orderInfo.passenger_info && orderInfo.passenger_info.mobile">
					<view class="column-title">乘车信息</view>
					<view class="column-value flex justify-content-end">
						<text class="text" v-if="orderInfo.passenger_info.name">{{orderInfo.passenger_info.name}}</text>
						<text class="text">{{orderInfo.passenger_info.mobile}}</text>
					</view>
				</view>
				<view class="content-column" style="background: #FFF;" v-if="orderInfo.remarks">
					<view class="column-title">备注信息</view>
					<view class="column-value">{{orderInfo.remarks}}</view>
				</view>
				<view class="content-space"></view>
			</view>
			<!-- 已接单 -->
			<view class="main-content" v-else-if="orderInfo.state == 'accepted'">
				<view class="content-header flex align-items-center">
					<view class="header-title flex-item" v-if="orderInfo.driver_arrive_status == 'not_arrived'">
						<view class="title">正在前往出发地</view>
						<view class="subtitle">请尽快抵达出发地</view>
					</view>
					<view class="header-title flex-item" v-else>
						<view class="flex align-items-center">
							<text class="title">已到达出发地</text>
							<view class="title-time flex align-items-center" v-if="waitingTime">
								<view class="time-bg" :style="{background: themeColor}"></view>
								<text class="time-text" :style="{color: themeColor}">等待时间</text>
								<text class="time-value" :style="{color: themeColor}">{{waitingTime}}</text>
							</view>
						</view>
						<view class="subtitle">已到达出发地点，请尽快与乘客联系</view>
					</view>
					<view class="header-btn" @click="handleCancel()">取消订单</view>
				</view>
				<view class="content-passenger flex align-items-center">
					<view class="passenger-info flex-item flex align-items-center">
						<image class="avatar" :src="orderInfo.passenger_info.avatar" mode="aspectFill"></image>
						<view class="nickname">{{orderInfo.passenger_info.mobile}}</view>
					</view>
					<view class="passenger-btn" @click="sendMessage()">
						<image class="btn-icon" src="/static/document.png" mode="aspectFit"></image>
						<text class="btn-text">发消息</text>
						<view class="btn-point" v-if="parseInt(orderInfo.unread_count) > 0"></view>
					</view>
					<view class="passenger-btn" @click="onContact()">
						<image class="btn-icon" src="/static/phone.png" mode="aspectFit"></image>
						<text class="btn-text">拨打电话</text>
					</view>
				</view>
				<view class="content-order">
					<view class="order-group flex align-items-center" :style="{'--group-color': '#242629'}">
						<view class="group-point"></view>
						<view class="group-text flex-item">{{orderInfo.from_address}}</view>
						<view class="group-btn" v-if="orderInfo.driver_arrive_status == 'not_arrived'" @click="handleNavigation(1)">前往导航</view>
					</view>
					<view class="order-group flex align-items-center" :style="{'--group-color': themeColor}">
						<view class="group-point"></view>
						<view class="group-text flex-item">{{orderInfo.to_address}}</view>
						<view class="group-btn" v-if="orderInfo.driver_arrive_status == 'arrived'" @click="handleNavigation(2)">前往导航</view>
					</view>
					<view class="order-time">{{orderInfo.departure_time}}</view>
				</view>
				<view class="content-column" v-if="orderInfo.remarks">
					<view class="column-title">备注信息</view>
					<view class="column-value">{{orderInfo.remarks}}</view>
				</view>
				<view class="content-space"></view>
			</view>
			<!-- 行程中 -->
			<view class="main-content" v-else-if="orderInfo.state == 'in_progress'">
				<view class="content-header flex align-items-center">
					<view class="header-title flex-item">
						<view class="title">正在前往目的地</view>
						<view class="subtitle">请尽快抵达目的地</view>
					</view>
				</view>
				<view class="content-passenger flex align-items-center">
					<view class="passenger-info flex-item flex align-items-center">
						<image class="avatar" :src="orderInfo.passenger_info.avatar" mode="aspectFill"></image>
						<view class="nickname">{{orderInfo.passenger_info.mobile}}</view>
					</view>
					<view class="passenger-btn" @click="sendMessage()">
						<image class="btn-icon" src="/static/document.png" mode="aspectFit"></image>
						<text class="btn-text">发消息</text>
						<view class="btn-point" v-if="parseInt(orderInfo.unread_count) > 0"></view>
					</view>
					<view class="passenger-btn" @click="onContact()">
						<image class="btn-icon" src="/static/phone.png" mode="aspectFit"></image>
						<text class="btn-text">拨打电话</text>
					</view>
				</view>
				<view class="content-order">
					<view class="order-group flex align-items-center" :style="{'--group-color': '#242629'}">
						<view class="group-point"></view>
						<view class="group-text flex-item">{{orderInfo.from_address}}</view>
					</view>
					<view class="order-group flex align-items-center" :style="{'--group-color': themeColor}">
						<view class="group-point"></view>
						<view class="group-text flex-item">{{orderInfo.to_address}}</view>
						<view class="group-btn" @click="handleNavigation(2)">前往导航</view>
					</view>
					<view class="order-time">{{orderInfo.departure_time}}</view>
				</view>
				<view class="content-column" v-if="orderInfo.remarks">
					<view class="column-title">备注信息</view>
					<view class="column-value">{{orderInfo.remarks}}</view>
				</view>
				<view class="content-space"></view>
			</view>
			<!-- 待补差 -->
			<view class="main-content" v-else-if="orderInfo.state == 'awaiting_payment'">
				<view class="content-header flex align-items-center">
					<view class="header-title flex-item">
						<view class="title">行程结束</view>
						<view class="subtitle">本次行程已结束，等待补差价</view>
					</view>
				</view>
				<view class="content-passenger flex align-items-center">
					<view class="passenger-info flex-item flex align-items-center">
						<image class="avatar" :src="orderInfo.avatar" mode="aspectFill"></image>
						<view class="nickname">尾号{{orderInfo.mobile}}</view>
					</view>
					<view class="passenger-amount"><text class="text">{{orderInfo.actual_amount}}</text>元</view>
				</view>
				<view class="content-order">
					<view class="order-group flex align-items-center" :style="{'--group-color': '#242629'}">
						<view class="group-point"></view>
						<view class="group-text flex-item">{{orderInfo.from_address}}</view>
					</view>
					<view class="order-group flex align-items-center" :style="{'--group-color': themeColor}">
						<view class="group-point"></view>
						<view class="group-text flex-item">{{orderInfo.to_address}}</view>
					</view>
					<view class="order-time">{{orderInfo.departure_time}}</view>
				</view>
				<view class="content-column">
					<view class="column-title">补差金额</view>
					<view class="column-value">{{orderInfo.awaiting_payment_pay_amount}}</view>
				</view>
				<view class="content-column" v-if="orderInfo.remarks">
					<view class="column-title">备注信息</view>
					<view class="column-value">{{orderInfo.remarks}}</view>
				</view>
				<view class="content-space" v-if="orderInfo.awaiting_payment_status == 1"></view>
			</view>
			<!-- 已完成 -->
			<view class="main-content" v-else-if="orderInfo.state == 'completed' || orderInfo.state == 'refunded'">
				<view class="content-header flex align-items-center">
					<view class="header-title flex-item">
						<view class="title">行程结束</view>
						<view class="subtitle">本次行程已结束，请提示乘客确认安全到达！</view>
					</view>
				</view>
				<!-- 样式1 -->
				<block v-if="completedStyle == 2">
					<view class="content-amount">
						<view class="price"><text class="text">{{orderInfo.actual_amount}}</text>元</view>
						<view class="tips">行程费用</view>
					</view>
					<view class="content-info">
						<view class="info-number">订单编号：{{orderInfo.order_no}}</view>
						<view class="info-box">
							<view class="box-passenger flex-item flex align-items-center">
								<image class="avatar" :src="orderInfo.avatar" mode="aspectFill"></image>
								<view class="nickname">尾号{{orderInfo.mobile}}</view>
							</view>
							<view class="box-group flex align-items-center" :style="{'--group-color': '#242629'}">
								<view class="group-point"></view>
								<view class="group-text flex-item">{{orderInfo.from_address}}</view>
							</view>
							<view class="box-group flex align-items-center" :style="{'--group-color': themeColor}">
								<view class="group-point"></view>
								<view class="group-text flex-item">{{orderInfo.to_address}}</view>
							</view>
							<view class="box-time">{{orderInfo.arrive_time}}</view>
						</view>
					</view>
				</block>
				<!-- 样式2 -->
				<block v-else>
					<view class="content-passenger flex align-items-center">
						<view class="passenger-info flex-item flex align-items-center">
							<image class="avatar" :src="orderInfo.avatar" mode="aspectFill"></image>
							<view class="nickname">尾号{{orderInfo.mobile}}</view>
						</view>
						<view class="passenger-amount"><text class="text">{{orderInfo.actual_amount}}</text>元</view>
					</view>
					<view class="content-order">
						<view class="order-group flex align-items-center" :style="{'--group-color': '#242629'}">
							<view class="group-point"></view>
							<view class="group-text flex-item">{{orderInfo.from_address}}</view>
						</view>
						<view class="order-group flex align-items-center" :style="{'--group-color': themeColor}">
							<view class="group-point"></view>
							<view class="group-text flex-item">{{orderInfo.to_address}}</view>
						</view>
						<view class="order-time">{{orderInfo.departure_time}}</view>
					</view>
					<view class="content-column" v-if="orderInfo.remarks">
						<view class="column-title">备注信息</view>
						<view class="column-value">{{orderInfo.remarks}}</view>
					</view>
				</block>
			</view>
			<!-- 已取消 -->
			<view class="main-content" v-else-if="orderInfo.state == 'cancelled'">
				<view class="content-header flex align-items-center" v-if="orderInfo.driver_receive_compensation_amount">
					<view class="header-title flex-item">
						<view class="title">用户违规取消订单</view>
						<view class="subtitle">已为您进行补偿金额<text :style="{color: themeColor}">￥{{orderInfo.driver_receive_compensation_amount}}</text></view>
					</view>
				</view>
				<view class="content-order" :style="!orderInfo.driver_receive_compensation_amount ? 'margin-top: 0;' : ''">
					<view class="order-group flex align-items-center">
						<view class="group-point" style="background: #242629;"></view>
						<view class="group-text flex-item">{{orderInfo.from_address}}</view>
					</view>
					<view class="order-group flex align-items-center">
						<view class="group-point" :style="{background: themeColor}"></view>
						<view class="group-text flex-item">{{orderInfo.to_address}}</view>
					</view>
					<view class="order-time">{{orderInfo.departure_time}}</view>
				</view>
				<view class="content-cancel">
					<view class="cancel-title">订单已取消</view>
					<view class="cancel-subtitle">如有疑问请与平台进行联系</view>
				</view>
			</view>
			<!-- IOS底部安全区 -->
			<view class="safe-padding"></view>
		</view>
		<view class="container-footer" v-if="orderInfo.state == 'pending' || orderInfo.state == 'accepted' || orderInfo.state == 'in_progress' || (orderInfo.state == 'awaiting_payment' && orderInfo.awaiting_payment_status == 1)">
			<view class="flex align-items-center" v-if="orderInfo.state == 'pending'">
				<view class="footer-price flex-item">￥<text class="text">{{orderInfo.actual_amount}}</text></view>
				<view class="footer-btn" style="width: 312rpx;border-radius: 48rpx;" @click="handleGrabOrder()">立即抢单</view>
			</view>
			<view class="footer-btn" v-else-if="orderInfo.state == 'accepted' && orderInfo.driver_arrive_status == 'not_arrived'" @click="handleArrived()">我已到达</view>
			<block v-else-if="orderInfo.state == 'accepted' && orderInfo.driver_arrive_status == 'arrived'">
				<view class="flex align-items-center" v-if="orderInfo.confirm_mobile_tail_number == 1">
					<view class="footer-btn plain flex-item" @click="handleUpload()">
						<view class="btn-bg"></view>
						<text class="btn-text">上传车辆图片</text>
					</view>
					<text class="footer-btn flex-item ml-8" :style="{background: themeColor}" @click="handleStart()">开始行程</text>
				</view>
				<view class="footer-btn" @click="handleConfirm()" v-else>确认手机尾号</view>
			</block>
			<view class="flex align-items-center" v-else-if="orderInfo.state == 'in_progress'">
				<view class="footer-btn" :style="{background: themeColor}" @click="handleContinue()" v-if="orderInfo.waiting_start_time">继续行程<text v-if="waitingTime">({{waitingTime}})</text></view>
				<view class="footer-btn" style="background: #F9602E;" @click="handleWaiting()" v-else>中途等待</view>
				<view class="footer-btn" style="background: #353C57;" @click="handleEnd()">到达目的地</view>
			</view>
			<view class="flex align-items-center" v-else-if="orderInfo.state == 'awaiting_payment' && orderInfo.awaiting_payment_status == 1">
				<view class="footer-btn" :style="{background: themeColor}" @click="handleRefresh()">刷新订单</view>
				<view class="footer-btn" style="background: #353C57;" @click="openPaymentCode()">补差二维码</view>
			</view>
			<view class="safe-padding"></view>
		</view>
		<!-- 确认乘客信息弹窗 -->
		<confirm-passenger ref="confirmPassenger" @onChange="pageChange" @onConfirm="passengerConfirm"></confirm-passenger>
		<!-- 上传照片弹窗 -->
		<photograph-modal ref="photographModal" @onChange="pageChange" @onConfirm="photographConfirm"></photograph-modal>
		<!-- 二维码弹窗 -->
		<payment-code-modal ref="paymentCodeModal" show-type="1" @onChange="pageChange" @onUpdate="getOrderDetails()"></payment-code-modal>
	</view>
</template>

<script>
	import { mapState } from "vuex"
	import confirmPassenger from "@/pages/driver/component/modal/confirm-passenger.vue"
	import photographModal from "@/pages/driver/component/modal/photograph.vue"
	import paymentCodeModal from "@/pages/driver/component/modal/payment-code.vue"
	import recorderUtil from '@/common/recorder.js';
	export default {
		components: {
			confirmPassenger,
			photographModal,
			paymentCodeModal,
		},
		data() {
			return {
				// 页面是否阻止滚动
				pageShow: false,
				// 加载完成
				loadEnd: false,
				// 是否重新定位
				isResetLocation: false,
				// 当前地址
				currentLocation: null,
				// 地图标记点
				markersList: [],
				// 上一次标记点数据
				lastMapMarkers: [],
				// 地图显示的标记点
				showMarkers: [],
				// 地图缩放数据
				mapScalePoints: [],
				// 地图信息
				mapInfo: {
					latitude: "",
					longitude: "",
				},
				// 轨迹点
				polyline: [{
					points: [],
					color: "#00C47A", //线的颜色
					width: 8, //线的宽度
				}],
				// 订单id
				orderId: null,
				// 订单状态
				orderState: "",
				// 订单数据
				orderInfo: {},
				// 已完成样式
				completedStyle: 1,
				// 等待时间
				waitingTime: "00:00",
				// 等待时间定时器
				waitingTimeTimer: null,
				// 延时器
				timeout: null,
				// 路线参数
				// routeInfo: [],
				// 实时监听位置方法
				locationChangeFn: null,
				// 是否定时提交路径
				isSubmitRoute: false,
				// 定时更新订单
				updateOrderTimer: null,
				// 是否开启定时更新
				isOpenUpdateOrder: true,
				// 自动定位
				centerMap: 1,
				// 安全中心信息
				securityInfo: null,
				// 是否拒绝录音
				isRefuseRecording: false,
				// 是否启动录音
				isOpenRecorder: false,
				// 录音管理器实例
				recorderManager: null,
				// 当前录音状态 1.正在录音，2.未录音，3.录音暂停
				recorderStatus: 2,
				// 最长录音时间（秒）
				maxRecorderTime: 60,
			}
		},
		computed: {
			...mapState({
				themeColor: state => state.app.themeColor,
				subscribeNotifyIds: state => state.app.subscribeNotifyIds,
			})
		},
		onLoad(option) {
			this.orderId = option.id || option.scene
			this.orderState = option.state || ""
			uni.showLoading({
				title: "加载中"
			})
			if (option.state == "in_progress") this.getSecurityInfo()
			if (option.state == "accepted" || option.state == "in_progress") {
				this.getAuthSetting(() => {
					this.getOrderDetails(() => {
						uni.hideLoading()
						this.loadEnd = true
					})
				})
			} else {
				this.getOrderDetails(() => {
					uni.hideLoading()
					this.loadEnd = true
				})
			}
		},
		onShow() {
			this.isOpenUpdateOrder = true
			if (this.loadEnd) {
				this.getOrderDetails()
			} else if (this.isResetLocation) {
				this.isResetLocation = false
				this.getAuthSetting(() => {
					this.getOrderDetails(() => {
						uni.hideLoading()
						this.loadEnd = true
					})
				})
			}
		},
		onPullDownRefresh() {
			if (this.orderState == "accepted" || this.orderState == "in_progress") {
				this.getAuthSetting(() => {
					this.getOrderDetails(() => {
						uni.stopPullDownRefresh()
					})
				})
			} else {
				this.getOrderDetails(() => {
					uni.stopPullDownRefresh()
				})
			}
		},
		onUnload() {
			if (this.timeout) clearTimeout(this.timeout)
			if (this.waitingTimeTimer) clearTimeout(this.waitingTimeTimer)
			this.isOpenUpdateOrder = false
			if (this.updateOrderTimer) clearTimeout(this.updateOrderTimer)
			// if (this.locationChangeFn) wx.offLocationChange(this.locationChangeFn)
			if (this.recorderStatus == 1 || this.recorderStatus == 3) this.endRecord()
		},
		onHide() {
			this.isOpenUpdateOrder = false
			if (this.updateOrderTimer) clearTimeout(this.updateOrderTimer)
		},
		methods: {
			// 改变页面滚动状态
			pageChange(state) {
				this.pageShow = state
			},
			// 初始化地图
			initMap(number = 0) {
				try {
					this._mapContext = uni.createMapContext("map", this);
					this._mapContext.initMarkerCluster({
						enableDefaultStyle: false,
						zoomOnClick: true,
						gridSize: 60,
					});
					this._mapContext.on("markerClusterCreate", () => {});
				} catch (error) {
					if (++number < 10) {
						setTimeout(() => {
							this.initMap(number)
						}, 200);
					}
				}
			},
			// 获取位置权限
			async getAuthSetting(fn) {
				try {
					const permissionStatus = await this.$util.checkLocationPermission()
					if (permissionStatus == 1) {
						this.getLocationChange(fn)
					} else {
						this.$util.setLocationPermission(permissionStatus, (result) => {
							if (result) {
								// #ifdef MP-WEIXIN
								this.getLocationChange(fn)
								// #endif
								// #ifdef APP
								this.isResetLocation = true
								// #endif
							} else {
								if (fn) fn()
								this.currentLocation = null
							}
						})
					}
				} catch (error) {
					this.currentLocation = null
					if (fn) fn()
					uni.showToast({
						title: error.message,
						icon: 'none',
						duration: 2000,
					})
				}
			},
			// 获取持续定位
			getLocationChange(fn) {
				uni.getLocation({
					type: 'gcj02',
					geocode: true,
					success: (res) => {
						this.currentLocation = {
							latitude: res.latitude,
							longitude: res.longitude,
						}
						if (fn) fn()
					},
					fail: () => {
						if (fn) fn()
					},
				})
				// this.locationChangeFn = (res) => {
				// 	this.currentLocation = {
				// 		latitude: res.latitude,
				// 		longitude: res.longitude,
				// 	}
				// 	if (fn) {
				// 		fn()
				// 		fn = null
				// 	}
				// 	if (this.isSubmitRoute) {
				// 		var points = JSON.parse(JSON.stringify(this.routeInfo))
				// 		if (points.length > 0) {
				// 			var oldValue = points[points.length - 1]
				// 			var curDistance = this.getDistance(oldValue.lat, oldValue.lng, this.currentLocation.latitude, this.currentLocation.longitude)
				// 			if (curDistance > 0.2) {
				// 				this.routeInfo.push({
				// 					lat: this.currentLocation.latitude,
				// 					lng: this.currentLocation.longitude,
				// 				})
				// 			}
				// 		} else {
				// 			this.routeInfo.push({
				// 				lat: this.currentLocation.latitude,
				// 				lng: this.currentLocation.longitude,
				// 			})
				// 		}
				// 		if (this.routeInfo.length >= 0 && this.routeInfo.length %5 == 0) this.submitRoute()
				// 	}
				// }
				// wx.startLocationUpdateBackground({
				// 	success: (res) => {
				// 		wx.onLocationChange(this.locationChangeFn)
				// 	},
				// 	fail: (err) => {
				// 		console.error('获取当前位置失败', err)
				// 	}
				// })
			},
			// 获取订单详情
			getOrderDetails(fn) {
				let data = { id: this.orderId }
				if (this.orderState == "accepted" || this.orderState == "in_progress") {
					if (this.currentLocation) {
						data.driver_lng = this.currentLocation.longitude
						data.driver_lat = this.currentLocation.latitude
					} else {
						this.getAuthSetting(() => {
							if (this.currentLocation) {
								this.getOrderDetails(() => {
									if (fn) fn()
								})
							} else {
								uni.hideLoading()
								uni.showModal({
									title: "系统提示",
									content: "定位失败，请稍后再试",
									showCancel: false,
									confirmText: "我知道了",
									success: () => {
										if (getCurrentPages().length == 1) {
											this.$util.toPage({
												mode: 3,
												path: "/pages/driver/index/index"
											})
										} else {
											uni.navigateBack()
										}
									}
								})
							}
						})
						return
					}
				}
				this.$util.request("driver.order.details", data).then(res => {
					if (res.code == 1) {
						if (fn) fn()
						this.$nextTick(() => {
							this.initMap()
						})
						this.orderInfo = res.data
						this.orderState = res.data.state
						this.polyline = [{
							points: [],
							color: "#00C47A",
							arrowLine: true,
							width: 8,
						}]
						this.markersList = []
						this.mapScalePoints = []
						if (this.updateOrderTimer) clearTimeout(this.updateOrderTimer)
						if (this.orderInfo.state == "pending" || this.orderInfo.state == "accepted" || this.orderInfo.state == "in_progress") {
							if (this.isOpenUpdateOrder) {
								this.updateOrderTimer = setTimeout(() => {
									this.updateOrder()
								}, 2500);
							}
						}
						if (this.orderState == "in_progress" && !this.isRefuseRecording) {
							if (this.securityInfo) {
								this.isOpenRecorder = true
								this.startRecord()
							} else {
								this.getSecurityInfo(() => {
									this.isOpenRecorder = true
									this.startRecord()
								})
							}
						} else if (this.isOpenRecorder) {
							this.isOpenRecorder = false
							if (this.recorderStatus != 2) this.recorderManager.endRecord()
						}
						if (this.orderInfo.state == "pending") {
							this.mapInfo = {
								latitude: res.data.to_lat,
								longitude: res.data.to_lng,
							}
							this.orderInfo.distance = this.$util.meterToKilometer(res.data.routes[0].distance, 2)
							var pl = this.transformRoute(res.data.routes[0].polyline)
							if (pl.length == 1) pl.push({ latitude: res.data.from_lat, longitude: res.data.from_lng })
							this.polyline = [{
								points: pl,
								color: "#00C47A",
								arrowLine: true,
								width: 8,
							}]
							this.markersList = [{
									id: 1,
									latitude: pl[0].latitude,
									longitude: pl[0].longitude,
									iconPath: "/static/location_s.png",
									width: 20,
									height: 39,
									customCallout: {
										anchorX: 0,
										anchorY: -4,
										display: "ALWAYS",
									},
								},
								{
									id: 2,
									latitude: pl[pl.length - 1].latitude,
									longitude: pl[pl.length - 1].longitude,
									iconPath: "/static/location_e.png",
									width: 20,
									height: 39,
									customCallout: {
										anchorX: 0,
										anchorY: -4,
										display: "ALWAYS",
									},
								},
							]
							this.mapScalePoints = pl
						} else if (this.orderState == "accepted") {
							if (this.currentLocation) {
								this.mapInfo = this.currentLocation
								var pl = this.transformRoute(res.data.routes[0].polyline)
								if (pl.length == 1) pl.push({ latitude: res.data.from_lat, longitude: res.data.from_lng })
								if (this.orderInfo.driver_arrive_status == 'not_arrived') {
									this.polyline = [{
										points: pl,
										color: "#00C47A",
										arrowLine: true,
										width: 8,
									}]
									this.markersList = [{
											id: 3,
											latitude: pl[0].latitude,
											longitude: pl[0].longitude,
											iconPath: "/static/avatar.png",
											width: 32,
											height: 32,
										},
										{
											id: 4,
											latitude: pl[pl.length - 1].latitude,
											longitude: pl[pl.length - 1].longitude,
											iconPath: "/static/location_s.png",
											width: 20,
											height: 39,
										},
									]
									this.mapScalePoints = pl
								} else {
									this.markersList = [{
											id: 5,
											latitude: pl[0].latitude,
											longitude: pl[0].longitude,
											iconPath: "/static/car.png",
											width: 48,
											height: 32,
											customCallout: {
												anchorX: 0,
												anchorY: -4,
												display: "ALWAYS",
											},
										},
										{
											id: 6,
											latitude: pl[pl.length - 1].latitude,
											longitude: pl[pl.length - 1].longitude,
											iconPath: "/static/location_s.png",
											width: 20,
											height: 39,
										},
									]
									this.mapScalePoints = pl
									this.getWaitingTime()
								}
							} else {
								this.mapInfo = {
									latitude: res.data.from_lat,
									longitude: res.data.from_lng,
								}
								if (this.orderInfo.driver_arrive_status == 'arrived') {
									this.markersList = [{
										id: 5,
										latitude: this.orderInfo.from_lat,
										longitude: this.orderInfo.from_lng,
										iconPath: "/static/location_s.png",
										width: 20,
										height: 39,
										customCallout: {
											anchorX: 0,
											anchorY: -4,
											display: "ALWAYS",
										},
									}]
									this.getWaitingTime()
								} else {
									this.markersList = [{
										id: 3,
										latitude: this.orderInfo.from_lat,
										longitude: this.orderInfo.from_lng,
										iconPath: "/static/location_s.png",
										width: 20,
										height: 39,
									}]
								}
							}
						} else if (this.orderState == "in_progress") {
							if (res.data.waiting_start_time) {
								this.getWaitingTime()
							}
							var pl = this.transformRoute(res.data.routes[0].polyline)
							if (pl.length == 1) pl.push({ latitude: res.data.to_lat, longitude: res.data.to_lng })
							if (this.currentLocation) {
								this.mapInfo = this.currentLocation
								this.polyline = [{
									points: pl,
									color: "#00C47A",
									arrowLine: true,
									width: 8,
								}]
								this.markersList = [{
										id: 7,
										latitude: pl[0].latitude,
										longitude: pl[0].longitude,
										iconPath: "/static/car.png",
										width: 48,
										height: 32,
									},
									{
										id: 8,
										latitude: pl[pl.length - 1].latitude,
										longitude: pl[pl.length - 1].longitude,
										iconPath: "/static/location_e.png",
										width: 20,
										height: 39,
									},
								]
								this.mapScalePoints = pl
							} else {
								this.mapInfo = {
									latitude: pl[0].latitude,
									longitude: pl[0].longitude,
								}
								this.markersList = [{
									id: 7,
									latitude: pl[0].latitude,
									longitude: pl[0].latitude,
									iconPath: "/static/location_e.png",
									width: 20,
									height: 39,
								}]
							}
						} else if (this.orderState == "awaiting_payment" || this.orderState == "refunded" || this.orderState == "completed" || this.orderState == "cancelled") {
							var pl = this.transformRoute(res.data.routes[0].polyline)
							if (pl.length == 1) pl.push({ latitude: res.data.to_lat, longitude: res.data.to_lng })
							this.mapInfo = {
								latitude: res.data.to_lat,
								longitude: res.data.to_lng,
							}
							this.polyline = [{
								points: pl,
								color: "#AEAEAE",
								arrowLine: true,
								width: 8,
							}]
							this.markersList = [{
									id: 9,
									latitude: pl[0].latitude,
									longitude: pl[0].longitude,
									iconPath: "/static/point_s.png",
									width: 20,
									height: 39,
								},
								{
									id: 10,
									latitude: pl[pl.length - 1].latitude,
									longitude: pl[pl.length - 1].longitude,
									iconPath: "/static/point_e.png",
									width: 20,
									height: 39,
								},
							]
							this.mapScalePoints = pl
						}
						this.$nextTick(() => this.setMapMarkers())
						this.$forceUpdate()
					} else {
						uni.hideLoading()
						uni.showModal({
							title: "系统提示",
							content: res.msg,
							showCancel: false,
							confirmText: "我知道了",
							success: () => {
								if (getCurrentPages().length == 1) {
									this.$util.toPage({
										mode: 3,
										path: "/pages/driver/index/index"
									})
								} else {
									uni.navigateBack()
								}
							}
						})
					}
				}).catch(error => {
					if (fn) fn()
					console.error('获取订单详情 ', error)
				})
			},
			// 转换路线经纬度
			transformRoute(coors) {
				var result = []
				// 腾讯地图
				for (var i = 2; i < coors.length; i++) {
					coors[i] = coors[i - 2] + coors[i] / 1000000
				}
				for (var i = 0; i < coors.length; i += 2) {
					result.push({ latitude: coors[i], longitude: coors[i + 1] })
				}
				return result
			},
			// 设置地图标记点
			setMapMarkers(number = 0) {
				if (this._mapContext) {
					const addMarkers = () => {
						this.showMarkers = []
						this.$nextTick(() => {
							this.showMarkers = this.lastMapMarkers = this.markersList
							this.setMapScale()
						})
					}
					try {
						if (this.lastMapMarkers.length && this.markersList.length) {
							var isUpdate = false
							this.markersList.forEach((item, index) => {
								if (item.id == this.lastMapMarkers[index].id) {
									const distance = this.getDistance(item.latitude, item.longitude, this.lastMapMarkers[index].latitude, this.lastMapMarkers[index].longitude)
									if (isNaN(distance) || Number(distance) < 0 || Number(distance) >= 1) {
										isUpdate = true
									}
								} else {
									isUpdate = true
								}
							});
							if (isUpdate) addMarkers()
						} else {
							addMarkers()
						}
					} catch (error) {
						addMarkers()
					}
				} else {
					if (number < 5) {
						setTimeout(() => {
							this.setMapMarkers(++number)
						}, 200);
					}
				}
			},
			// 设置地图缩放
			setMapScale(number) {
				if (!this.mapScalePoints.length || this.centerMap != 1) return
				setTimeout(() => {
					this._mapContext.includePoints({
						points: this.mapScalePoints,
						padding: [100, 100, 80, 100],
						fail: () => {
							if (number < 10) this.setMapScale(++number)
						},
					});
				}, 200);
			},
			// 跳转安全中心
			toSecurity() {
				this.$util.toPage({
					mode: 1,
					path: "/pages/driver/mine/security/index",
					isToken: true,
				})
			},
			// 抢单
			handleGrabOrder() {
				uni.showLoading({
					title: "加载中",
					mask: true,
				})
				this.subscribeMessage(() => {
					this.$util.request("driver.order.grabOrder", {
						id: this.orderId
					}).then(res => {
						uni.hideLoading()
						if (res.code == 1) {
							uni.showToast({
								icon: "success",
								title: "接单成功"
							})
							this.orderState = "accepted"
							this.$store.commit('app/setDriverSocket', 1)
							this.getAuthSetting(() => {
								this.getOrderDetails()
							})
						} else {
							uni.showToast({
								title: res.msg,
								icon: 'none'
							})
						}
					}).catch(error => {
						uni.hideLoading()
						console.error('抢单 ', error)
					})
				})
			},
			// 订阅消息
			subscribeMessage(fn) {
				// #ifdef MP-WEIXIN
				var tmplIds = []
				if (this.subscribeNotifyIds?.applet_passenger_cancellation_order_notice) tmplIds.push(this.subscribeNotifyIds.applet_passenger_cancellation_order_notice)
				uni.requestSubscribeMessage({
					tmplIds,
					success: () => {
						fn()
					},
					fail: (error) => {
						uni.hideLoading()
						if (error.errCode == 20004) {
							uni.showModal({
								title: '提示',
								content: '请前往设置打开接受通知',
								confirmColor: this.themeColor,
								confirmText: '继续提交',
								success: (res) => {
									if (res.confirm) {
										uni.showLoading({
											title: "加载中",
											mask: true
										})
										fn()
									}
								},
							})
						} else {
							uni.showModal({
								title: '提示',
								content: '消息订阅失败，无法接收到订单通知，错误码：' + error.errCode,
								confirmColor: this.themeColor,
								confirmText: '继续提交',
								success: (res) => {
									if (res.confirm) {
										uni.showLoading({
											title: "加载中",
											mask: true
										})
										fn()
									}
								},
							})
						}
					}
				})
				// #endif
				// #ifndef MP-WEIXIN
				fn()
				// #endif
			},
			// 拨打电话
			onContact() {
				this.$util.toPage({
					mode: 6,
					phone: this.orderInfo.passenger_info.fictitious_mobile,
				})
			},
			// 发送消息
			sendMessage() {
				this.$util.toPage({
					mode: 1,
					path: `/pages/driver/message/details?id=${this.orderId}&name=${this.orderInfo.passenger_info.mobile}`,
					isToken: true,
				})
			},
			// 取消订单
			handleCancel() {
				uni.showModal({
					title: "系统提示",
					content: "确定取消该订单吗？",
					confirmColor: this.themeColor,
					success: (res) => {
						if (res.confirm) {
							uni.showLoading({
								title: "加载中",
								mask: true,
							})
							this.$util.request("driver.order.cancel", {
								id: this.orderId
							}).then(res => {
								uni.hideLoading()
								if (res.code == 1) {
									this.isStopUpdateOrder = true
									uni.showToast({
										icon: "success",
										title: "取消成功",
										mask: true
									})
									this.timeout = setTimeout(() => {
										uni.navigateBack()
									}, 1500);
								} else {
									uni.showToast({
										title: res.msg,
										icon: 'none'
									})
								}
							}).catch(error => {
								uni.hideLoading()
								console.error('抢单 ', error)
							})
						}
					}
				})
			},
			// 前往导航
			handleNavigation(type) {
				var data = {}
				if (type == 1) {
					data = {
						name: this.orderInfo.from_address,
						latitude: this.orderInfo.from_lat,
						longitude: this.orderInfo.from_lng,
					}
				} else {
					data = {
						name: this.orderInfo.to_address,
						latitude: this.orderInfo.to_lat,
						longitude: this.orderInfo.to_lng,
					}
				}
				let osName = "";
				// #ifdef MP-WEIXIN
				osName = uni.getDeviceInfo().osName;
				// #endif
				// #ifndef MP-WEIXIN
				osName = uni.getSystemInfoSync().osName;
				// #endif
				if (osName == "ios") {
					uni.openLocation({
						name: data.name,
						longitude: Number(data.longitude),
						latitude: Number(data.latitude),
					});
				} else {
					this._mapContext.openMapApp({
						destination: data.name,
						longitude: Number(data.longitude),
						latitude: Number(data.latitude),
						fail: () => {
							uni.openLocation({
								name: data.name,
								longitude: Number(data.longitude),
								latitude: Number(data.latitude),
							});
						},
					})
				}
			},
			// 我已到达
			handleArrived() {
				uni.showLoading({
					title: "加载中",
					mask: true,
				})
				this.getAuthSetting(() => {
					if (!this.currentLocation) return
					this.$util.request("driver.order.arrived", {
						id: this.orderId,
						lat: this.currentLocation.latitude,
						lng: this.currentLocation.longitude,
					}).then(res => {
						if (res.code == 1) {
							this.getOrderDetails(() => uni.hideLoading())
						} else {
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none'
							})
						}
					}).catch(error => {
						uni.hideLoading()
						console.error('我已到达 ', error)
					})
				})
			},
			// 确认乘客手机尾号
			handleConfirm() {
				this.$refs.confirmPassenger.open()
			},
			// 确认乘客信息弹窗回调
			passengerConfirm(number) {
				uni.showLoading({
					title: "加载中",
					mask: true,
				})
				this.$util.request("driver.order.confirmMobile", {
					id: this.orderId,
					tail_number: number,
				}).then(res => {
					if (res.code == 1) {
						this.getOrderDetails(() => {
							uni.hideLoading()
							this.$refs.confirmPassenger.onClose()
						})
					} else {
						uni.hideLoading()
						uni.showToast({
							title: res.msg,
							icon: 'none'
						})
					}
				}).catch(error => {
					uni.hideLoading()
					console.error('确认乘客手机尾号 ', error)
				})
			},
			// 上传车辆图片
			handleUpload() {
				this.$refs.photographModal.open(1, this.orderInfo.start_itinerary_take_pictures)
			},
			// 上传照片弹窗回调
			photographConfirm(type, images) {
				if (type == 1) {
					this.$util.request("driver.order.startItineraryPictures", {
						id: this.orderId,
						start_itinerary_take_pictures: images || "",
					}).then(res => {
						if (res.code == 1) {
							this.getOrderDetails(() => {
								uni.hideLoading()
								uni.showToast({
									icon: "success",
									title: "上传成功",
									duration: 2000
								})
								this.$refs.photographModal.onClose()
							})
						} else {
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none'
							})
						}
					}).catch(error => {
						uni.hideLoading()
						console.error('开始行程上传图片 ', error)
					})
				} else if (type == 2) {
					this.$util.request("driver.order.endItinerary", {
						id: this.orderId,
						lat: this.currentLocation.latitude,
						lng: this.currentLocation.longitude,
						arrive_at_take_pictures: images || "",
					}).then(res => {
						if (res.code == 1) {
							this.getOrderDetails(() => {
								this.completedStyle = 2
								uni.hideLoading()
								this.$refs.photographModal.onClose()
							})
						} else {
							uni.hideLoading()
							uni.showToast({
								title: res.msg,
								icon: 'none'
							})
						}
					}).catch(error => {
						uni.hideLoading()
						console.error('到达目的地 ', error)
					})
				}
			},
			// 开始行程
			handleStart() {
				if (this.orderInfo.start_itinerary_take_pictures?.length) {
					this.startItinerary()
				} else {
					uni.showModal({
						content: ' 当前未上传车辆图片信息， \n 是否直接开始行程？ ',
						confirmText: "开始行程",
						confirmColor: this.themeColor,
						cancelText: '上传图片',
						cancelColor: '#8D929C',
						success: (res) => {
							if (res.confirm) {
								this.startItinerary()
							} else if (res.cancel) {
								this.handleUpload()
							}
						}
					})
				}
			},
			// 开始行程
			startItinerary() {
				uni.showLoading({
					title: "加载中",
					mask: true,
				})
				this.$util.request("driver.order.startItinerary", {
					id: this.orderId,
				}).then(res => {
					if (res.code == 1) {
						this.getOrderDetails(() => uni.hideLoading())
					} else {
						uni.hideLoading()
						uni.showToast({
							title: res.msg,
							icon: 'none'
						})
					}
				}).catch(error => {
					uni.hideLoading()
					console.error('开始行程 ', error)
				})
			},
			// 更新订单
			updateOrder() {
				if (this.orderInfo.state == "pending") {
					this.getOrderDetails()
				} else {
					this.getLocationChange(() => {
						if (this.orderState == "accepted") {
							this.$util.request("driver.driverCenter.update", {
								driver_lat: this.currentLocation.latitude,
								driver_lng: this.currentLocation.longitude,
							})
						}
						this.getOrderDetails()
					})
				}
			},
			// 拖拽地图
			regionchange(obj) {
				if (obj.type == "begin" && this.centerMap === 1) {
					this.centerMap = 2
				} else if (obj.causedBy != "drag" && this.centerMap === 2) {
					this.centerMap = 1
				} else {
					this.centerMap = 0
					setTimeout(() => {
						this.centerMap = 1
					}, 5000);
				}
			},
			// 定时提交路线
			// submitRoute() {
			// 	const inspectionPoints = JSON.parse(JSON.stringify(this.routeInfo))
			// 	this.routeInfo = []
			// 	this.$util.request("driver.order.submitRoute", {
			// 		order_id: this.orderId,
			// 		data: JSON.stringify(inspectionPoints)
			// 	}).then(res => {
			// 		if (res.code != 1) {
			// 			this.routeInfo = inspectionPoints
			// 		}
			// 	}).catch(error => {
			// 		this.routeInfo = inspectionPoints
			// 		console.error('定时提交路线 ', error)
			// 	})
			// },
			// 根据经纬度计算距离
			getDistance(lat1, lng1, lat2, lng2) {
				var radLat1 = lat1 * Math.PI / 180.0;
				var radLat2 = lat2 * Math.PI / 180.0;
				var a = radLat1 - radLat2;
				var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
				var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
				s = s * 6378.137 * 1000;
				s = parseFloat(s).toFixed(2)
				return s;
			},
			// 获取等待时间
			getWaitingTime() {
				const startTime = this.orderInfo.waiting_start_time * 1000
				const updateTime = () => {
					const nowTime = new Date().getTime()
					const timeDiff = nowTime - startTime;
					if (timeDiff < 0) {
						this.waitingTime = "00:00:00"
						return
					}
					var hours = Math.floor(timeDiff / 3600000);
					var minutes = Math.floor(timeDiff / 60000) % 60;
					var seconds = Math.floor(timeDiff / 1000) % 60;
					hours >= 0 && hours <= 9 ? (hours = "0" + hours) : ""
					minutes >= 0 && minutes <= 9 ? (minutes = "0" + minutes) : ""
					seconds >= 0 && seconds <= 9 ? (seconds = "0" + seconds) : ""
					if (parseInt(hours) == 0) {
						this.waitingTime = `${minutes}:${seconds}`
					} else if (parseInt(hours) > 999) {
						this.waitingTime = null
					} else {
						this.waitingTime = `${hours}:${minutes}:${seconds}`
					}
					if (this.waitingTimeTimer) clearTimeout(this.waitingTimeTimer)
					this.waitingTimeTimer = setTimeout(() => {
						updateTime()
					}, 1000);
				}
				if (this.waitingTimeTimer) clearTimeout(this.waitingTimeTimer)
				updateTime()
			},
			// 中途等待
			handleWaiting() {
				uni.showLoading({
					title: "加载中",
					mask: true,
				})
				this.$util.request("driver.order.waiting", {
					order_id: this.orderId,
				}).then(res => {
					if (res.code == 1) {
						this.getOrderDetails(() => uni.hideLoading())
					} else {
						uni.hideLoading()
						uni.showToast({
							title: res.msg,
							icon: 'none'
						})
					}
				}).catch(error => {
					uni.hideLoading()
					console.error('中途等待 ', error)
				})
			},
			// 继续行程
			handleContinue() {
				uni.showLoading({
					title: "加载中",
					mask: true,
				})
				this.$util.request("driver.order.continue", {
					id: this.orderId,
				}).then(res => {
					if (res.code == 1) {
						this.getOrderDetails(() => uni.hideLoading())
					} else {
						uni.hideLoading()
						uni.showToast({
							title: res.msg,
							icon: 'none'
						})
					}
				}).catch(error => {
					uni.hideLoading()
					console.error('继续行程 ', error)
				})
			},
			// 到达目的地
			handleEnd() {
				uni.showLoading({
					title: "加载中",
					mask: true,
				})
				this.getAuthSetting(() => {
					uni.hideLoading()
					if (!this.currentLocation) return
					this.$refs.photographModal.open(2)
				})
			},
			// 刷新订单
			handleRefresh() {
				uni.showLoading({
					title: "加载中",
					mask: true
				})
				this.getOrderDetails(() => {
					uni.hideLoading()
					uni.showToast({
						icon: "success",
						title: "刷新成功"
					})
				})
			},
			// 打开补差二维码
			openPaymentCode() {
				this.$refs.paymentCodeModal.open(this.orderId)
			},
			// 获取安全中心信息
			getSecurityInfo(fn) {
				this.$util.request("driver.security").then(res => {
					if (res.code == 1) {
						this.securityInfo = res.data || {}
						if (fn) fn()
					} else {
						this.securityInfo = {}
					}
				}).catch(error => {
					this.securityInfo = {}
					console.error('获取安全中心信息 ', error)
				})
			},
			// 初始化录音管理器
			initRecorder() {
				this.recorderManager = new recorderUtil(this.maxRecorderTime);
				this.recorderManager.onMessage(res => {
					this.recorderStatus = res.status
					if (res.type == "permission_denied") {
						this.isRefuseRecording = true
						uni.showModal({
							content: ' 检测到您没打开麦克风权限， \n 是否前往设置？ ',
							confirmText: "确认",
							confirmColor: this.themeColor,
							cancelText: '取消',
							success: (res) => {
								if (res.confirm) {
									this.isRefuseRecording = false
									// #ifdef MP-WEIXIN
									uni.openSetting()
									// #endif
									// #ifdef APP
									this.recorderManager.gotoAppPermissionSetting()
									// #endif
								}
							}
						})
					} else if (res.type == "start") {
						this.isOpenRecorder = true
					} else if (res.type == "stop") {
						this.uploadAudio(res)
					}
				});
			},
			// 开始录音
			startRecord() {
				if (this.isOpenRecorder && this.securityInfo.sound_recording_status == 1) {
					if (!this.recorderManager) this.initRecorder()
					if (this.recorderStatus == 2) {
						this.recorderManager.startRecord()
					} else if (this.recorderStatus == 3) {
						this.recorderManager.resumeRecord()
					}
				} else {
					if (this.recorderStatus == 1 || this.recorderStatus == 3) {
						this.endRecord()
					}
				}
			},
			// 结束录音
			endRecord() {
				this.recorderManager.endRecord()
			},
			// 上传录音文件
			uploadAudio(audio) {
				this.$util.uploadFile(audio.path).then(result => {
					if (result.code == 1) {
						this.$util.request("main.recording.submit", {
							order_id: this.orderId,
							url: result.data.url,
							start_time: audio.start_time,
							end_time: audio.end_time,
							source: 2,
						})
					}
				}).catch(error => {
					console.error('上传录音 ', error)
				})
			},
		}
	}
</script>

<style lang="scss">
	page {
		padding-bottom: 0;
	}

	.container {
		min-height: 100vh;
		position: relative;

		.container-map {
			position: sticky;
			top: 0;
			width: 100%;
			height: 100%;
			min-height: 500rpx;

			.map-box {
				width: 100%;
				height: 100%;
				position: absolute;
				top: 0;
				left: 0;

				.map-callout {
					width: 100vw;
					display: flex;
					flex-direction: row;
					justify-content: center;
				}

				.callout-address {
					border-radius: 8rpx;
					background: #FFF;
					box-shadow: 0 4rpx 8rpx 0 rgba(0, 0, 0, 0.25);
					padding: 14rpx;
					display: flex;
					flex-direction: row;
					align-items: center;
					max-width: 160px;

					.address-name {
						color: #242629;
						font-size: 24rpx;
						font-weight: 600;
						line-height: 34rpx;
						white-space: pre-wrap;
					}
				}

				.callout-box {
					border-radius: 16rpx;
					background: #FFF;
					min-width: 160px;

					.box-title {
						color: #000;
						text-align: center;
						font-size: 28rpx;
						font-weight: 600;
						line-height: 40rpx;
						padding: 16rpx 16rpx 0;
					}

					.box-subtitle {
						margin-top: 12rpx;
						color: var(--theme-color);
						text-align: center;
						font-size: 28rpx;
						font-weight: 600;
						line-height: 40rpx;
						padding: 0 16rpx 16rpx;
					}
				}
			}
		}

		.container-main {
			position: relative;
			z-index: 9;
			margin-top: -32rpx;
			border-radius: 32rpx 32rpx 0 0;
			background: #FFF;

			.main-content {
				padding: 32rpx;

				.content-card {
					padding: 32rpx;
					border-radius: 16rpx;
					background: #FFF;

					.card-title {
						color: #242629;
						font-size: 28rpx;
						font-weight: 600;
						line-height: 40rpx;
					}

					.card-group {
						margin-top: 32rpx;

						.group-point {
							width: 16rpx;
							height: 16rpx;
							border-radius: 50%;
							background: var(--group-color);
						}

						.group-text {
							margin-left: 16rpx;
							color: var(--group-color);
							font-size: 28rpx;
							font-weight: 600;
							line-height: 40rpx;
						}
					}
				}

				.content-column {
					margin-top: 32rpx;
					border-radius: 16rpx;
					background: #F7F7F7;
					padding: 32rpx;
					display: flex;
					flex-direction: row;

					.column-title {
						color: #242629;
						font-size: 28rpx;
						font-weight: 600;
						line-height: 40rpx;
					}

					.column-value {
						flex: 1;
						color: #242629;
						font-size: 28rpx;
						font-weight: 600;
						line-height: 40rpx;
						margin-left: 48rpx;
						display: flex;
						flex-direction: row;
						justify-content: flex-end;

						.text {
							margin-left: 24rpx;

							&:first-child {
								margin-left: 0;
							}
						}
					}
				}

				.content-space {
					width: 100%;
					height: 128rpx;
				}

				.content-header {
					.header-title {
						.title {
							color: #242629;
							font-size: 32rpx;
							font-weight: 600;
							line-height: 44rpx;
						}

						.subtitle {
							color: #8D929C;
							font-size: 28rpx;
							line-height: 40rpx;
							margin-top: 8rpx;
						}

						.title-time {
							margin-left: 24rpx;

							.time-text {
								font-size: 28rpx;
								font-weight: 400;
								line-height: 40rpx;
							}

							.time-value {
								font-size: 28rpx;
								font-weight: 600;
								line-height: 40rpx;
								margin-left: 16rpx;
							}
						}
					}

					.header-btn {
						color: var(--theme-color);
						font-size: 24rpx;
						font-weight: 600;
						line-height: 34rpx;
						padding: 6rpx 14rpx;
						border-radius: 12px;
						border: 1px solid var(--theme-color);
						margin-left: 32rpx;
					}
				}

				.content-passenger {
					margin-top: 16rpx;

					.passenger-info {
						.avatar {
							width: 64rpx;
							height: 64rpx;
							border-radius: 50%;
						}

						.nickname {
							margin-left: 32rpx;
							color: #242629;
							font-size: 32rpx;
							font-weight: 600;
							line-height: 44rpx;
						}
					}

					.passenger-btn {
						min-width: 144rpx;
						padding: 16rpx 24rpx;
						display: flex;
						flex-direction: column;
						align-items: center;
						margin-left: 24rpx;

						.btn-icon {
							width: 32rpx;
							height: 32rpx;
						}

						.btn-text {
							margin-top: 8rpx;
							color: #242629;
							text-align: center;
							font-size: 24rpx;
							line-height: 34rpx;
						}

						.btn-point {
							position: absolute;
							top: 8rpx;
							right: 24rpx;
							border-radius: 16rpx;
							width: 16rpx;
							height: 16rpx;
							background: #DE2828;
						}
					}

					.passenger-amount {
						color: #242629;
						font-size: 24rpx;
						line-height: 100rpx;

						.text {
							font-size: 20px;
							font-weight: 600;
						}
					}
				}

				.content-order {
					padding: 32rpx;
					border-radius: 32rpx;
					background: #F7F7F7;
					margin-top: 32rpx;

					.order-group {
						margin-top: 32rpx;

						&:first-child {
							margin-top: 0;
						}

						.group-point {
							width: 16rpx;
							height: 16rpx;
							border-radius: 50%;
							background: var(--group-color);
						}

						.group-text {
							margin-left: 16rpx;
							color: var(--group-color);
							font-size: 28rpx;
							font-weight: 600;
							line-height: 40rpx;
						}

						.group-btn {
							color: var(--theme-color);
							font-size: 28rpx;
							line-height: 40rpx;
							margin-left: 24rpx;
						}
					}

					.order-time {
						color: #242629;
						font-size: 28rpx;
						font-weight: 600;
						line-height: 40rpx;
						margin-top: 32rpx;
					}
				}

				.content-amount {
					margin-top: 64rpx;

					.price {
						color: #242629;
						text-align: center;
						font-size: 32rpx;
						line-height: 100rpx;

						.text {
							font-size: 72rpx;
							font-weight: 600;
						}
					}

					.tips {
						margin-top: 16rpx;
						color: #8D929C;
						text-align: center;
						font-size: 28rpx;
						line-height: 40rpx;
					}
				}

				.content-info {
					margin-top: 64rpx;
					border-radius: 16rpx;
					background: #F7F7F7;

					.info-number {
						color: #8D929C;
						font-size: 28rpx;
						line-height: 40rpx;
						padding: 16rpx 32rpx;
						border-bottom: 1px solid #EEE;
					}

					.info-box {
						padding: 32rpx;

						.box-passenger {
							.avatar {
								width: 64rpx;
								height: 64rpx;
								border-radius: 50%;
							}

							.nickname {
								margin-left: 32rpx;
								color: #242629;
								font-size: 32rpx;
								font-weight: 600;
								line-height: 44rpx;
							}
						}

						.box-group {
							margin-top: 32rpx;

							.group-point {
								width: 16rpx;
								height: 16rpx;
								border-radius: 50%;
								background: var(--group-color);
							}

							.group-text {
								margin-left: 16rpx;
								color: var(--group-color);
								font-size: 28rpx;
								font-weight: 600;
								line-height: 40rpx;
							}
						}

						.box-time {
							color: #242629;
							font-size: 28rpx;
							font-weight: 600;
							line-height: 40rpx;
							margin-top: 32rpx;
						}
					}
				}

				.content-cancel {
					padding: 32rpx;
					border-radius: 32rpx;
					background: #F7F7F7;
					margin-top: 32rpx;

					.cancel-title {
						color: #242629;
						font-size: 32rpx;
						font-weight: 600;
						line-height: 44rpx;
					}

					.cancel-subtitle {
						margin-top: 32rpx;
						color: #8D929C;
						font-size: 24rpx;
						line-height: 34rpx;
					}
				}
			}
		}

		.container-footer {
			position: fixed;
			left: 0;
			right: 0;
			bottom: 0;
			z-index: 96;
			padding: 16rpx 32rpx 16rpx 38rpx;
			background: #FFF;

			.footer-price {
				color: #DE2828;
				font-size: 28rpx;
				font-weight: 600;
				line-height: 62rpx;
				margin-right: 16rpx;

				.text {
					color: #DE2828;
					font-size: 44rpx;
					font-weight: 600;
					line-height: 62rpx;
				}
			}

			.footer-btn {
				width: 100%;
				margin-left: 16rpx;
				color: #FFF;
				text-align: center;
				font-size: 28rpx;
				font-weight: 600;
				line-height: 40rpx;
				padding: 28rpx;
				border-radius: 32rpx;
				background: var(--theme-color);
				overflow: hidden;

				&:first-child {
					margin-left: 0;
				}

				&.plain {
					position: relative;
					padding: 28rpx;
					background: transparent;

					.btn-bg {
						position: absolute;
						top: 0;
						right: 0;
						bottom: 0;
						left: 0;
						opacity: .1;
						background: var(--theme-color);
					}

					.btn-text {
						position: relative;
						z-index: 1;
						color: var(--theme-color);
						text-align: center;
						font-size: 28rpx;
						font-weight: 600;
						line-height: 40rpx;
					}
				}
			}
		}
	}
</style>